package com.ls.fw.office.itext.itext.builder;

import java.awt.Color;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;

import com.lowagie.text.Element;
import com.lowagie.text.Font;
import com.lowagie.text.Image;
import com.lowagie.text.Phrase;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.ls.fw.commons.core.utils.date.DateTypeUtil;
import com.ls.fw.office.itext.helper.CellMapper;
import com.ls.fw.office.itext.helper.FieldMapper;

/**
 * pdf table
 * 
 * @author Defender 2014年5月25日下午7:02:42
 */
public class TableBuilder {

	private int columns = 0;// 列数
	private final PdfPTable table; // pdf table

	private int colCounter = 0;// 列计数器
	//private PdfPCell lastCellUsed;
	private Object lastCellUsed;
	private Class<?> lastCellUsedType;
	private boolean newLine = true;

	public TableBuilder(int columns) {
		this.columns = columns;
		table = new PdfPTable(columns);
	}

	public TableBuilder(float... columnWidths) {
		this.columns = columnWidths.length;
		table = new PdfPTable(columnWidths);
	}

	public TableBuilder addCell(Object value) {
		return this.addCell(value, null);
	}
	
	
	public TableBuilder addCell(Object value,Font font) {
		if(Image.class.isAssignableFrom(value.getClass())){
			this.addCell((Image)value);
		}else if(Phrase.class.isAssignableFrom(value.getClass())){
			this.addCell((Phrase)value);
		}else if(PdfPCell.class.isAssignableFrom(value.getClass())){
			this.addCell((PdfPCell)value);
		}else if(PdfPTable.class.isAssignableFrom(value.getClass())){
			this.addCell((PdfPTable)value);
		}else{
			this.addCell(String.valueOf(value),font);
		}
		return this;
	}

	public TableBuilder addCell(Image value) {
		addLastCell();
		this.lastCellUsed = value;
		this.lastCellUsedType = Image.class;
		colCounter++;
		return this;
	}

	public TableBuilder addCell(PdfPTable value) {
		addLastCell();
		this.lastCellUsed = value;
		this.lastCellUsedType = PdfPTable.class;
		colCounter++;
		return this;
	}
	
	public TableBuilder addCell(Phrase value) {
		addLastCell();
		this.lastCellUsed = value;
		this.lastCellUsedType = Phrase.class;
		colCounter++;
		return this;
	}
	public TableBuilder addCell(PdfPCell value) {
		addLastCell();
		this.lastCellUsed = value;
		this.lastCellUsedType = PdfPCell.class;
		colCounter++;
		return this;
	}

	public TableBuilder addCell(String text) {
		return this.addCell(text,null);
	}
	
	public TableBuilder addCell(String text, Font font) {
		return this.addCell(ParagraphBuilder.newParagraph(text).setFont(font));
	}

	public TableBuilder addCell(ParagraphBuilder paragraphBuilder) {
		addLastCell();
		lastCellUsed = new PdfPCell(paragraphBuilder.getParagraph());
		this.lastCellUsedType = PdfPCell.class;
		colCounter++;
		return this;
	}

	 
	public TableBuilder creatHead(String... head) {
		return this.creatHead(ParagraphBuilder.zh_h2HeadingFont, head);
	}
	
	public TableBuilder creatHead(Font font, String... head) {
		this.flush();
		if (!this.newLine) {
			this.forceNewRow();
		}
		for (String string : head) {
			this.addCell(ParagraphBuilder.newParagraph(string).setFont(font));
		}
		return this;
	}

	public <T> TableBuilder addRow(final Collection<T> dataset) {
		this.addRow(dataset,null, null);
		return this;
	}

	public <T> TableBuilder addRow(final Collection<T> dataset, Font font) {
		this.addRow(dataset,font, null);
		return this;
	}
	
	public <T> TableBuilder addRow(final Collection<T> dataset, 
			FieldMapper mapper) {
		this.addRow(dataset,null, mapper);
		return this;
	}
	
	public <T> TableBuilder addRow(final Collection<T> dataset, 
			Font font,FieldMapper mapper) {
		this.addRow(dataset,font, mapper,null);
		return this;
	}
	
	
	public <T> TableBuilder addRow(final Collection<T> dataset, 
			Font font, FieldMapper mapper,CellMapper cellMapper) {
		Iterator<T> it = dataset.iterator();
		while (it.hasNext()) {
			this.flush();
			if (!this.newLine) {
				this.forceNewRow();
			}
			T t = (T) it.next();
			Field[] fields = t.getClass().getDeclaredFields();
			for (short i = 0; i < fields.length; i++) {
				Field field = fields[i];
				String fieldName = field.getName();
				String bffix = "get";
				// if(field.getType().equals(boolean.class)){
				// bffix = "is";
				// }
				String getMethodName = bffix
						+ fieldName.substring(0, 1).toUpperCase()
						+ fieldName.substring(1);
				try {
					Class<? extends Object> tCls = t.getClass();
					Method getMethod = tCls.getMethod(getMethodName,
							new Class[] {});
					Object value = getMethod.invoke(t, new Object[] {});
					if (mapper != null) {
						value = mapper.mapper(fieldName, value, i);
					}
					if (value instanceof Date) {
						value = DateTypeUtil.toString(value);
					}
					this.addCell(value,font);
					if(cellMapper!=null){
						cellMapper.handl(fieldName, this.lastCellUsed, this.lastCellUsedType);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		return this;
	}

	
	public TableBuilder withSpacingBefore(float spacingBefore) {
		table.setSpacingBefore(spacingBefore);
		return this;
	}

	/**
	 * 设置最近处理的cell所占列数
	 * 
	 * @author Defender 2014年5月25日下午7:01:05
	 * @param colSpan
	 * @return
	 */
	public TableBuilder withColSpan(int colSpan) {
		colCounter += colSpan - 1;
		if(this.lastCellUsedType.equals(Image.class)){
			// ((Image)lastCellUsed).setColspan(colSpan);
		}else if(this.lastCellUsedType.equals(Phrase.class)){
			//((Phrase)lastCellUsed).setColspan(colSpan);
		}else if(this.lastCellUsedType.equals(PdfPCell.class)){
			((PdfPCell)lastCellUsed).setColspan(colSpan);
		}else if(this.lastCellUsedType.equals(PdfPTable.class)){
			//((PdfPTable)lastCellUsed).setColspan(colSpan);
		}  
		return this;
	}

	public TableBuilder withLeftAlignment() {
		if(this.lastCellUsedType.equals(Image.class)){
			 //((Image)lastCellUsed).setHorizontalAlignment(Element.ALIGN_LEFT);
		}else if(this.lastCellUsedType.equals(Phrase.class)){
			//((Phrase)lastCellUsed).setHorizontalAlignment(Element.ALIGN_LEFT);
		}else if(this.lastCellUsedType.equals(PdfPCell.class)){
			((PdfPCell)lastCellUsed).setHorizontalAlignment(Element.ALIGN_LEFT);
		}else if(this.lastCellUsedType.equals(PdfPTable.class)){
			((PdfPTable)lastCellUsed).setHorizontalAlignment(Element.ALIGN_LEFT);
		}  
		return this;
	}

	public TableBuilder withRightAlignment() {
		if(this.lastCellUsedType.equals(Image.class)){
			 //((Image)lastCellUsed).setHorizontalAlignment(Element.ALIGN_RIGHT);
		}else if(this.lastCellUsedType.equals(Phrase.class)){
			//((Phrase)lastCellUsed).setHorizontalAlignment(Element.ALIGN_RIGHT);
		}else if(this.lastCellUsedType.equals(PdfPCell.class)){
			((PdfPCell)lastCellUsed).setHorizontalAlignment(Element.ALIGN_RIGHT);
		}else if(this.lastCellUsedType.equals(PdfPTable.class)){
			((PdfPTable)lastCellUsed).setHorizontalAlignment(Element.ALIGN_RIGHT);
		}  
		return this;
	}

	public TableBuilder withCenterAlignment() {
		if(this.lastCellUsedType.equals(Image.class)){
			 //((Image)lastCellUsed).setHorizontalAlignment(Element.ALIGN_CENTER);
		}else if(this.lastCellUsedType.equals(Phrase.class)){
			//((Phrase)lastCellUsed).setHorizontalAlignment(Element.ALIGN_CENTER);
		}else if(this.lastCellUsedType.equals(PdfPCell.class)){
			((PdfPCell)lastCellUsed).setHorizontalAlignment(Element.ALIGN_CENTER);
		}else if(this.lastCellUsedType.equals(PdfPTable.class)){
			((PdfPTable)lastCellUsed).setHorizontalAlignment(Element.ALIGN_CENTER);
		}  
		return this;
	}

	public TableBuilder withNoBorder() {
		table.getDefaultCell().setBorder(Rectangle.NO_BORDER);
		table.getDefaultCell().setBackgroundColor(new Color(255, 255, 255));
		return this;
	}

	/**
	 * 刷新文档
	 * 
	 * @author Defender 2014年5月25日下午8:37:06
	 * @return
	 */
	public TableBuilder flush() {
		addLastCell();
		return this;
	}

	/**
	 * 将光标移到下一行
	 * 
	 * @author Defender 2014年5月25日下午6:57:51
	 * @return
	 */
	public TableBuilder forceNewRow() {
		addLastCell();
		while (colCounter < columns) {
			table.addCell("");
			colCounter++;
		}
		colCounter = 0;
		this.newLine = true;
		return this;
	}

	private void addLastCell() {
		if (lastCellUsed != null) {
			if(this.lastCellUsedType.equals(Image.class)){
				table.addCell((Image)lastCellUsed);
			}else if(this.lastCellUsedType.equals(Phrase.class)){
				table.addCell((Phrase)lastCellUsed);
			}else if(this.lastCellUsedType.equals(PdfPCell.class)){
				table.addCell((PdfPCell)lastCellUsed);
			}else if(this.lastCellUsedType.equals(PdfPTable.class)){
				table.addCell((PdfPTable)lastCellUsed);
			}else{
				table.addCell(String.valueOf(lastCellUsed));
			}
			checkCounter();
		}
		lastCellUsed = null;
	}

	private void checkCounter() {
		if (colCounter >= columns) {
			colCounter = 0;
			newLine = true;
		} else {
			newLine = false;
		}
	}

	/**
	 * 获取pdf表
	 * 
	 * @author Defender 2014年5月25日下午6:58:41
	 * @return
	 */
	public PdfPTable getTable() {
		addLastCell();
		return table;
	}

	public PdfPCell getCell() {
		if(this.lastCellUsedType.equals(Image.class)){
			return ((PdfPCell)lastCellUsed);
		} 
		return null;
	}
	
	public Image getCellImage() {
		if(this.lastCellUsedType.equals(Image.class)){
			return ((Image)lastCellUsed);
		} 
		return null;
	}

	public Phrase getCellPhrase() {
	   if(this.lastCellUsedType.equals(Phrase.class)){
		   return ((Phrase)lastCellUsed);
		} 
		return null;
	}
	
	
	public PdfPTable getCellTable() {
		if(this.lastCellUsedType.equals(PdfPTable.class)){
			return ((PdfPTable)lastCellUsed);
		}
		return null;
	}
	
 
	/**
	 * 设置表宽度
	 * 
	 * @author Defender 2014年5月25日下午6:58:55
	 * @param tableWidth
	 * @return
	 */
	public TableBuilder withTableWidth(float tableWidth) {
		table.setWidthPercentage(tableWidth);
		return this;
	}

	/**
	 * 
	 * @author Defender 2014年5月25日下午6:59:16
	 * @param spacingAfter
	 * @return
	 */
	public TableBuilder withSpacingAfter(int spacingAfter) {
		table.setSpacingAfter(spacingAfter);
		return this;
	}

	/**
	 * 设置head所占行数
	 * 
	 * @author Defender 2014年5月25日下午6:59:41
	 * @param headerRow
	 * @return
	 */
	public TableBuilder withHeaderRow(int headerRow) {
		table.setHeaderRows(headerRow);
		return this;
	}

	/**
	 * 新建一个table
	 * 
	 * @author Defender 2014年5月25日下午7:00:12
	 * @param columns
	 * @return
	 */
	public static TableBuilder newTable(int columns) {
		return new TableBuilder(columns);
	}

	/**
	 * 新建一个table
	 * 
	 * @author Defender 2014年5月25日下午7:00:36
	 * @param columnWidths
	 * @return
	 */
	public static TableBuilder newTable(float... columnWidths) {
		return new TableBuilder(columnWidths);
	}

	public boolean isNewLine() {
		return newLine;
	}

}
